package com.isyscore.os.metadata.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.isyscore.os.core.exception.DataFactoryException;
import com.isyscore.os.core.exception.ErrorCode;
import com.isyscore.os.metadata.service.executor.FlowExecutor;
import com.isyscore.os.metadata.kettle.dto.FlowTaskPreviewDataDTO;
import com.isyscore.os.metadata.manager.DatabaseManager;
import com.isyscore.os.metadata.model.vo.DataQueryVO;
import com.isyscore.os.metadata.model.vo.ResultVO;
import com.isyscore.os.metadata.service.DataBuildService;
import com.isyscore.os.metadata.service.DataSourceService;
import com.isyscore.os.metadata.service.ETLFlowTaskPreviewDataService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author liy
 * @date 2022-07-13 10:50
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ETLFlowTaskPreviewDataServiceImpl implements ETLFlowTaskPreviewDataService {
    @Autowired
    DataSourceService dataSourceService;
    @Autowired
    DataBuildService dataBuildService;
    @Autowired
    private DatabaseManager databaseManager;

    @Override
    public FlowTaskPreviewDataDTO getTaskStepPreviewData(String taskId, String stepName) {
        List<List<String>> previewData = FlowExecutor.getPreviewData(taskId, stepName);
        if(CollectionUtil.isEmpty(previewData)){
            throw new DataFactoryException(ErrorCode.TASK_IS_FINISHED);
        }
        List<String> previewDataFields = FlowExecutor.getPreviewDataFields(taskId, stepName);
        FlowTaskPreviewDataDTO dto = new FlowTaskPreviewDataDTO();
        dto.setData(previewData);
        dto.setFields(previewDataFields);
        return dto;
    }

    @Override
    public FlowTaskPreviewDataDTO getTaskLastStepPreviewData(String taskId) {
        List<List<String>> previewData = FlowExecutor.getPreviewData(taskId);
        if(previewData==null){
            throw new DataFactoryException(ErrorCode.TASK_IS_FINISHED);
        }
        List<String> previewDataFields = FlowExecutor.getPreviewDataFields(taskId);
        FlowTaskPreviewDataDTO dto = new FlowTaskPreviewDataDTO();
        dto.setData(previewData);
        dto.setFields(previewDataFields);
        return dto;
    }

    @Override
    public FlowTaskPreviewDataDTO previewData(String sql, Long dataSourceId, String databaseName) {
        if(!sql.matches("^(?i)(\\s*)(select)(\\s+)(((?!(insert|delete|update|truncate|drop)).)+)$")){
            throw new DataFactoryException(ErrorCode.ONLY_SUPORT_SELECTSQL_ERROR);
        }
        FlowTaskPreviewDataDTO dto = new FlowTaskPreviewDataDTO();
        DataQueryVO dataQueryVO = new DataQueryVO();
        dataQueryVO.setDataSourceId(dataSourceId);
        dataQueryVO.setSqlText(sql);
        dataQueryVO.setDatabaseName(databaseName);
        ResultVO structureBySql = dataBuildService.getStructureBySql(dataQueryVO);

        List<String> fields = structureBySql.getHead().stream().map(f -> f.getColumnName() + "(" + f.getDataType() + ")").collect(Collectors.toList());
        dto.setFields(fields);
        List<List<String>> data  = new ArrayList<>();
        for (Map<String, Object> result : structureBySql.getContent()) {
            data.add(result.keySet().stream().map(k->String.valueOf(result.get(k))).collect(Collectors.toList()));
        }
        dto.setData(data);

        return dto;
    }
}
